﻿using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Server;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Xml;
using TicketM.ReportService;

namespace TicketM.Models
{
    public class Tickets
    {
        ArrayList assigneeList;
        ArrayList efforts;
        int ctr;
        static string ProcessConfigPath;
        private string RoutingConfigPath;
        private string TicketDefPath;
        private string ProjectsPath;
        public Tickets()
        {
            if (Process.GetCurrentProcess().ProcessName.ToLower().Contains("iisexpress"))
            {
                ProcessConfigPath = "/Configuration/TicketProcessingService.exe.config";
                RoutingConfigPath = "/App_Data/AreasStruct.xml";
                TicketDefPath = "/App_Data/Ticket.xml";
                ProjectsPath = "/App_Data/Projects.xml";
            }
            else
            {
                ProcessConfigPath = "/TicketM/Configuration/TicketProcessingService.exe.config";
                RoutingConfigPath = "/TicketM/App_Data/AreasStruct.xml";
                TicketDefPath = "/TicketM/App_Data/Ticket.xml";
                ProjectsPath = "/TicketM/App_Data/Projects.xml";
            }
        }
        /// <summary>
        /// This method gets all the tickets from a team project and converts their ID and Title in a DataTable which is then returned. 
        /// </summary>
        /// <param name="sProject">Session variable that stores the selected project and passed from page to this method</param>
        /// <returns></returns>
        public DataTable GetTickets(string sProject)
        {
            DataTable TicketsTable = new DataTable();
            DataColumn PkTicketIdColumn = TicketsTable.Columns.Add("TicketId", typeof(System.Int32));
            TicketsTable.Columns.Add("TicketTitle", typeof(string));
            try
            {
                #region Get Variable Values from existing config file
                string uName;
                string passwd;
                string domain;
                string tfs;
                string collection;
                string _project;
                SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
                #endregion

                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
                
                WorkItemStore wiStore = tpc.GetService<WorkItemStore>();
                Logger.CreateLogEntry(wiStore.Projects[0].Name);
                WorkItemCollection wiColl = wiStore.Query("SELECT [System.Id], [System.Title] FROM WorkItems WHERE [System.TeamProject] = '" + _project + "'  AND  [System.WorkItemType] = 'Ticket'");
                foreach (WorkItem wi in wiColl)
                {
                    DataRow TicketRow = TicketsTable.NewRow();
                    TicketRow["TicketId"] = wi.Id;
                    TicketRow["TicketTitle"] = wi.Title;
                    TicketsTable.Rows.Add(TicketRow);
                }
            }
            catch
            {
                
            }

            return TicketsTable;
        }

        public static TfsTeamProjectCollection Connect2Tfs(string uName, string passwd, string domain, string tfs, string collection)
        {
            NetworkCredential crednetial = new NetworkCredential(uName, passwd, domain);
            TfsTeamProjectCollection tpc;
            string _uri = "http://" + tfs + ":8080/tfs/" + collection;
            try
            {
                tpc = new TfsTeamProjectCollection(new Uri(_uri), crednetial);
            }
            catch
            {

                throw;
            }
            return tpc;
        }

        /// <summary>
        /// This method gets a ticket by its ID and adds the details into a table which is then returned
        /// </summary>
        /// <param name="id">Ticket ID passed by the calling page</param>
        /// <param name="sProject">Project Name passed by the calling page.</param>
        /// <returns></returns>
        public DataTable GetTicket(int id, string sProject)
        {
            DataTable TicketTable = new DataTable();
            TicketTable.Columns.Add("ID", typeof(System.Int32));
            TicketTable.Columns.Add("State", typeof(string));
            TicketTable.Columns.Add("Assigned To", typeof(string));
            TicketTable.Columns.Add("Description", typeof(string));

            try
            {
                #region Get Variable Values from existing config file
                string uName;
                string passwd;
                string domain;
                string tfs;
                string collection;
                string _project;
                SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
                #endregion

                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
                WorkItemStore wiStore = tpc.GetService<WorkItemStore>();
                WorkItem wi = wiStore.GetWorkItem(id);

                DataRow fldRow1 = TicketTable.NewRow();
                fldRow1["ID"] = wi.Id;
                fldRow1["State"] = wi.State;
                fldRow1["Assigned To"] = wi.Fields["System.AssignedTo"].Value.ToString();
                fldRow1["Description"] = wi.Description;
                TicketTable.Rows.Add(fldRow1);


            }
            catch
            {
                
            }
            return TicketTable;

        }

        /// <summary>
        /// This method takes a ticket ID and computes the time (in minutes) spent by each team member on that ticket
        /// </summary>
        /// <param name="id">Ticket ID passed by the calling page</param>
        /// <param name="sProject">Project Name passed by the calling page.</param>
        /// <returns></returns>
        public DataTable GetEfforts(int id, string sProject)
        {

            DataTable EffortsTable = new DataTable();
            EffortsTable.Columns.Add("Name", typeof(string));
            EffortsTable.Columns.Add("Efforts", typeof(System.Int32));
            try
            {
                #region Get Variable Values from existing config file
                string uName;
                string passwd;
                string domain;
                string tfs;
                string collection;
                string _project;
                SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
                #endregion

                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
                WorkItemStore wiStore = tpc.GetService<WorkItemStore>();
                WorkItem wi = wiStore.GetWorkItem(id);
                RevisionCollection revColl = wi.Revisions;
                Revision LastRev = null;
                foreach (Revision rev in revColl)
                {
                    LastRev = rev;
                }

                assigneeList = new ArrayList();
                efforts = new ArrayList();
                foreach (Revision rev in revColl)
                {
                    if (rev.Fields["System.AssignedTo"].Value.ToString() != rev.Fields["System.AssignedTo"].OriginalValue.ToString() && rev.Fields["System.AssignedTo"].OriginalValue.ToString() != "")
                    {

                        if (IsAssigneePresent(rev.Fields["System.AssignedTo"].OriginalValue.ToString()))
                        {
                            int eff = 0;
                            eff = Int32.Parse(efforts[ctr].ToString());
                            eff += Int32.Parse(rev.Fields["SSGS.MyEfforts"].Value.ToString());
                            efforts[ctr] = eff;
                        }
                        else
                        {
                            assigneeList.Add(rev.Fields["System.AssignedTo"].OriginalValue.ToString());
                            efforts.Add(Int32.Parse(rev.Fields["SSGS.MyEfforts"].Value.ToString()));
                        }
                    }
                }
                for (int i = 0; i < assigneeList.Count; i++)
                {
                    DataRow AssigneeRow = EffortsTable.NewRow();
                    AssigneeRow["Name"] = assigneeList[i].ToString();
                    AssigneeRow["Efforts"] = efforts[i].ToString();
                    EffortsTable.Rows.Add(AssigneeRow);
                }
            }
            catch
            {
                
            }
            return EffortsTable;
        }
        private bool IsAssigneePresent(string assignee)
        {
            bool assigneePresent = false;
            ctr = 0;
            if (assigneeList != null)
            {
                foreach (string candidate in assigneeList)
                {
                    if (candidate == assignee)
                    {
                        assigneePresent = true;
                        break;
                    }
                    ctr++;
                }
            }
            return assigneePresent;
        }
        /// <summary>
        /// This method reads the areas structure for a selected project
        /// </summary>
        /// <param name="sProject">Session variable that represents selected project</param>
        /// <returns></returns>
        public XmlDocument GetAreasStructure(string sProject)
        {
            #region Get Variable Values from existing config file
            string uName;
            string passwd;
            string domain;
            string tfs;
            string collection;
            string _project;
            SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
            #endregion

            try
            {
                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
                ICommonStructureService StructureService = (ICommonStructureService)tpc.GetService(typeof(ICommonStructureService));
                //Gets Area/Iteration base Project

                ProjectInfo projectInfo = StructureService.GetProjectFromName(_project);
                NodeInfo[] nodes = StructureService.ListStructures(projectInfo.Uri);
                XmlDocument doc1 = new XmlDocument();
                doc1.LoadXml(StructureService.GetNodesXml(new string[] { nodes[0].Uri }, true).InnerXml);
                XmlNodeList allNodes = doc1.FirstChild.SelectNodes("//*");
                return ProcessNode(allNodes, sProject);
            }
            catch
            {
                throw;
            }

        }
        /// <summary>
        /// This is a helper method that converts the passed nodes (areas) into a flat XmlDocument object
        /// </summary>
        /// <param name="allNodes">All area structure nodes for the selected project</param>
        /// <param name="sProject">Session variable representing selected project</param>
        /// <returns></returns>
        private XmlDocument ProcessNode(XmlNodeList allNodes, string sProject)
        {
            XmlDocument doc = new XmlDocument();
            XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", null, null);
            doc.AppendChild(dec);
            XmlElement root1 = doc.CreateElement("Project");
            XmlAttribute nameAttr = doc.CreateAttribute("Name");
            nameAttr.Value = sProject;
            root1.Attributes.Append(nameAttr);
            doc.AppendChild(root1);
            try
            {
                for (int i = 1; i < allNodes.Count; i++)
                {

                    if (allNodes[i].Name != "Children")
                    {
                        XmlNode elem = doc.CreateNode(XmlNodeType.Element, "SubArea", null);
                        XmlAttribute attrib = doc.CreateAttribute("Name");
                        //Structure service contains format that is not compatible further. So we need to process it first.
                        attrib.Value = allNodes[i].Attributes["Path"].Value.Split(new char[] { '\\' }, 4).GetValue(3).ToString();
                        elem.Attributes.Append(attrib);
                        root1.AppendChild(elem);
                    }
                }
            }
            catch
            {

                throw;
            }
            return doc;
        }
        /// <summary>
        /// This method reads the existing products from ticket work item type for a given project.
        /// The arraylist that is returened is bound to a datagrid on Products.aspx page
        /// </summary>
        /// <param name="sProject">Represents the session variable that contains selected project</param>
        /// <returns></returns>
        public ArrayList GetProductsList(string sProject)
        {
            ArrayList Products = new ArrayList();
            try
            {
                #region Get Variable Values from existing config file
                string uName;
                string passwd;
                string domain;
                string tfs;
                string collection;
                string _project;
                SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
                #endregion

                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
                var wiStore = tpc.GetService<WorkItemStore>();
                var project = wiStore.Projects[_project];
                WorkItemType wiType = project.WorkItemTypes["Ticket"];
                XmlDocument doc1 = wiType.Export(true);
                XmlNode root1 = doc1.DocumentElement;
                XmlNodeList nodes = root1.SelectNodes("//FIELDS/FIELD[@name='Product']/ALLOWEDVALUES/LISTITEM");
                foreach (XmlNode product in nodes)
                {
                    Products.Add(product.Attributes["value"].Value);
                }
            }
            catch
            {

                throw;
            }
            return Products;
        }
        /// <summary>
        /// This method updates the Ticket work item type for the selected project by adding the new product in the products list
        /// </summary>
        /// <param name="newProduct">Name of the new product to add</param>
        /// <param name="sProject">Session variable that represents the selected project</param>
        /// <returns></returns>
        public string SetProductsList(string newProduct, string sProject)
        {
            string returnMsg;
            try
            {
                #region Get Variable Values from existing config file
                string uName;
                string passwd;
                string domain;
                string tfs;
                string collection;
                string _project;
                SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
                #endregion

                //Connect to TFS and from the selected project get the XML of Ticket work item type definition
                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
                var wiStore = tpc.GetService<WorkItemStore>();
                var project = wiStore.Projects[_project];
                WorkItemType wiType = project.WorkItemTypes["Ticket"];
                XmlDocument doc1 = wiType.Export(true);
                XmlNode root1 = doc1.DocumentElement;


                //Check if the product already exists
                XmlNode item = root1.SelectSingleNode("//FIELDS/FIELD[@name='Product']/ALLOWEDVALUES/LISTITEM[@value=\"" + newProduct + "\"]");
                if (item == null) //if the product does not exists in the Ticket work item of that project create a node for that product
                {
                    XmlNode node = root1.SelectSingleNode("//FIELDS/FIELD[@name='Product']/ALLOWEDVALUES");
                    if (node == null)
                    {
                        XmlNode productNode = root1.SelectSingleNode("//FIELDS/FIELD[@name='Product']");
                        XmlNode NewAllowedValuesNode = doc1.CreateNode(XmlNodeType.Element, "ALLOWEDVALUES", null);
                        productNode.AppendChild(NewAllowedValuesNode);
                        node = NewAllowedValuesNode;
                    }
                    XmlNode NewProductNode = doc1.CreateNode(XmlNodeType.Element, "LISTITEM", null);
                    XmlAttribute valueAttrib = doc1.CreateAttribute("value");
                    valueAttrib.Value = newProduct;
                    NewProductNode.Attributes.Append(valueAttrib);

                    //append it at appropriate place
                    node.AppendChild(NewProductNode);
                    //import the work item type back in the same project
                    project.WorkItemTypes.Import(doc1.DocumentElement);
                    returnMsg = "Product Added";
                }
                else
                {
                    returnMsg = "Same named product found";
                }
            }
            catch
            {

                throw;
            }
            return returnMsg;
        }

        public static void SetGenVarValues(string sProject, out string uName, out string passwd, out string domain, out string tfs, out string collection, out string _project)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(HttpContext.Current.Server.MapPath(ProcessConfigPath));
                uName = doc.DocumentElement.SelectSingleNode("/configuration/appSettings/add[@key='UserName']").Attributes["value"].Value;
                passwd = doc.DocumentElement.SelectSingleNode("/configuration/appSettings/add[@key='Password']").Attributes["value"].Value;
                domain = doc.DocumentElement.SelectSingleNode("/configuration/appSettings/add[@key='Domain']").Attributes["value"].Value;
                tfs = doc.DocumentElement.SelectSingleNode("/configuration/appSettings/add[@key='Tfs']").Attributes["value"].Value;
                collection = doc.DocumentElement.SelectSingleNode("/configuration/appSettings/add[@key='Collection']").Attributes["value"].Value;
                _project = sProject;
            }
            catch
            {

                throw;
            }
        }

        /// <summary>
        /// This is a method in which the assignment constraints as set in ticket work item for selected project are read and stored in the AreasStruct.xml file
        /// </summary>
        /// <param name="docParam">This parameter is the current area structure read in GetAreaStructure method is passed on</param>
        /// <param name="sProject"></param>
        public void GetRoutingConditions(XmlDocument docParam, string sProject)
        {
            try
            {
                //The parameter docParam is the Area Structure of the selected project.
                #region Get Variable Values from existing config file
                string uName;
                string passwd;
                string domain;
                string tfs;
                string collection;
                string _project;
                SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
                #endregion
                //Connect to TFS
                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
                var wiStore = tpc.GetService<WorkItemStore>();
                var project = wiStore.Projects[_project];
                //Get the existing definition of Ticket WITD
                WorkItemType wiType = project.WorkItemTypes["Ticket"];
                //Export the Ticket WITD in a XML Document structure
                XmlDocument doc1 = wiType.Export(true);
                XmlNode root1 = doc1.DocumentElement;
                //Get the node for 'Assgined To' Field
                XmlNode node = root1.SelectSingleNode("//FIELDS/FIELD[@name='Assigned To']");


                int ctr = 0;
                //Get all nodes for Area from AreasStruct.xml file
                XmlNodeList areaNodes = docParam.FirstChild.NextSibling.SelectNodes("/*/*");
                //Read each area node    
                while (ctr < areaNodes.Count)
                {
                    string areaPath = areaNodes[ctr].Attributes["Name"].Value.ToString();
                    //Get Area Id for each area node        
                    int areaId = GetAreaId(areaPath, _project);
                    XmlNode defaultAssigneeNode = docParam.CreateNode(XmlNodeType.Element, "Assignee", null);
                    if (node.SelectSingleNode("WHEN[@value='" + areaId + "']/*/*") != null)
                    {
                        defaultAssigneeNode.InnerText = node.SelectSingleNode("WHEN[@value='" + areaId + "']/*/*").Attributes["value"].Value.ToString();

                        XmlNode root = docParam.DocumentElement;
                        XmlNode targetAreaNode = root.SelectSingleNode("/Project/SubArea[@Name='" + areaPath + "']");
                        targetAreaNode.AppendChild(defaultAssigneeNode);
                    }
                    ctr++;
                }
                docParam.Save(HttpContext.Current.Server.MapPath(RoutingConfigPath));
            }
            catch
            {

                throw;
            }

        }
        /// <summary>
        /// This method reads existing routing data from the configuration file AreasStruct.xml and converts it to a datatable.
        /// That datatable is bound to the datagrid on the Routing.aspx
        /// </summary>
        /// <param name="sProject">Session variable that represents selected project</param>
        /// <returns></returns>
        public DataTable ReadRoutingFromTFS(string sProject)
        {
            DataTable RoutingTable = new DataTable("RoutingTable");
            RoutingTable.Columns.Add("AreaPath", typeof(string));
            RoutingTable.Columns.Add("AssignedTo", typeof(string));

            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(HttpContext.Current.Server.MapPath(RoutingConfigPath));
                XmlNode ProjectNode = doc.DocumentElement.SelectSingleNode("/Project[@Name='" + sProject + "']");
                if (ProjectNode.HasChildNodes)
                {
                    XmlNodeList RoutingList = ProjectNode.ChildNodes;
                    foreach (XmlNode subarea in RoutingList)
                    {
                        DataRow dRow = RoutingTable.NewRow();
                        dRow["AreaPath"] = subarea.Attributes["Name"].Value.ToString();
                        if (subarea.HasChildNodes)
                            dRow["AssignedTo"] = subarea.FirstChild.InnerText;
                        else
                            dRow["AssignedTo"] = "";
                        RoutingTable.Rows.Add(dRow);
                    }
                }
            }
            catch
            {

                throw;
            }
            return RoutingTable;
        }
        public ArrayList GetTeamMembers(string sProject)
        {
            ArrayList UsersAL = new ArrayList();
            try
            {
                #region Get Variable Values from existing config file
                string uName;
                string passwd;
                string domain;
                string tfs;
                string collection;
                string _project;
                SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
                #endregion

                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
                var wiStore = tpc.GetService<WorkItemStore>();
                var project = wiStore.Projects[_project];
                var gss = tpc.GetService<IGroupSecurityService>();
                Identity SIDs = gss.ReadIdentity(SearchFactor.AccountName, "[" + project.Name + "]\\Contributors", QueryMembership.Expanded);
                Identity[] Users = gss.ReadIdentities(SearchFactor.Sid, SIDs.Members, QueryMembership.Direct);
                foreach (Identity user in Users)
                {

                    if (user.SecurityGroup)
                    {
                        UsersAL.Add("[project]\\" + user.DisplayName);
                    }
                    else
                    {
                        UsersAL.Add(user.DisplayName);
                    }

                }
            }
            catch
            {
                throw;
            }
            return UsersAL;
        }
        public ArrayList GetTeamMembersEmails(string sProject)
        {
            ArrayList UsersEmailsAL = new ArrayList();
            try
            {
                #region Get Variable Values from existing config file
                string uName;
                string passwd;
                string domain;
                string tfs;
                string collection;
                string _project;
                SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
                #endregion

                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
                var wiStore = tpc.GetService<WorkItemStore>();
                var project = wiStore.Projects[_project];
                var gss = tpc.GetService<IGroupSecurityService>();
                Identity SIDs = gss.ReadIdentity(SearchFactor.AccountName, "[" + project.Name + "]\\Contributors", QueryMembership.Expanded);
                Identity[] Users = gss.ReadIdentities(SearchFactor.Sid, SIDs.Members, QueryMembership.Direct);
                foreach (Identity user in Users)
                {

                    if (!user.SecurityGroup)
                    {
                        UsersEmailsAL.Add(user.MailAddress);
                    }
                }
            }
            catch
            {

                throw;
            }
            return UsersEmailsAL;
        }
        public int GetAreaId(string AreaPath, string sProject)
        {
            try
            {
                #region Get Variable Values from existing config file
                string uName;
                string passwd;
                string domain;
                string tfs;
                string collection;
                string _project;
                SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
                #endregion

                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
                var wiStore = tpc.GetService<WorkItemStore>();
                var project = wiStore.Projects[_project];
                NodeCollection nodes = project.AreaRootNodes;

                Node area = project.FindNodeInSubTree(AreaPath, Node.TreeType.Area);
                return area.Id;

            }
            catch
            {

                throw;
            }

        }

        /// <summary>
        /// This method synchornizes the escalation structure after changes are made
        /// </summary>
        /// <param name="doc">This represents the current area structure of the selected project</param>
        /// <param name="sProject">Session variable that represents the selected project</param>
        public void SyncEscalationStructure(XmlDocument doc, string sProject, string EscalationConfigPath )
        {
            try
            {
                XmlDocument EscalationArea = new XmlDocument();
                EscalationArea.Load(HttpContext.Current.Server.MapPath(EscalationConfigPath)); //Existing escalation accounts
                //Read existing nodes in the Areas of the project (passed as parameter by calling method)
                XmlNodeList AllAreas = doc.DocumentElement.SelectNodes("//SubArea");
                foreach (XmlNode area in AllAreas)
                {
                    //check if a node in AreaNoDaysEmails.xml config file exists for that area
                    if (EscalationArea.SelectSingleNode("/Area_Email_Days/Area[@Project='" + sProject + "' and @Name='" + area.Attributes["Name"].Value + "']") == null) //if project node is present but a specific area does not exist
                    {
                        //if that node does not exist, create one
                        XmlNode root = EscalationArea.DocumentElement;
                        XmlNode NewArea = EscalationArea.CreateNode(XmlNodeType.Element, "Area", null);
                        XmlAttribute NewAreaName = EscalationArea.CreateAttribute("Name");
                        XmlAttribute NewEmail = EscalationArea.CreateAttribute("Email");
                        XmlAttribute NewDays = EscalationArea.CreateAttribute("Days");
                        XmlAttribute NewProject = EscalationArea.CreateAttribute("Project");
                        //set standard values to attributes and area name as of selected area
                        NewEmail.Value = "";
                        NewDays.Value = "2";
                        NewAreaName.Value = area.Attributes["Name"].Value;
                        NewProject.Value = sProject;

                        NewArea.Attributes.Append(NewAreaName);
                        NewArea.Attributes.Append(NewDays);
                        NewArea.Attributes.Append(NewEmail);
                        NewArea.Attributes.Append(NewProject);
                        //append the node to the structure and save the file
                        root.AppendChild(NewArea);
                        EscalationArea.Save(HttpContext.Current.Server.MapPath(EscalationConfigPath));
                    }
                }
            }
            catch
            {

                throw;
            }
        }

        public ArrayList GetProjects()
        {
            ArrayList projects = new ArrayList();
            string uName;
            string passwd;
            string domain;
            string tfs;
            string collection;
            string _project;
            try
            {
                SetGenVarValues("", out uName, out passwd, out domain, out tfs, out collection, out _project);
                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
                WorkItemStore store = (WorkItemStore)tpc.GetService(typeof(WorkItemStore));
                foreach (Project project in store.Projects)
                {
                    projects.Add(project.Name);
                }
            }
            catch
            {

                throw;
            }
            return projects;

        }

        public bool AddTicketWIT2Project(string sProject, string ProjectsFilePath, string EscalationsFilePath)
        {
            bool retval = false;
            #region Get Variable Values from existing config file
            string uName;
            string passwd;
            string domain;
            string tfs;
            string collection;
            string _project;
            SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
            #endregion
            try
            {
                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
                var wiStore = tpc.GetService<WorkItemStore>();
                var project = wiStore.Projects[_project];
                XmlDocument doc1 = new XmlDocument();
                //doc1.Load(HttpContext.Current.Server.MapPath("/App_Data/Ticket.xml"));
                doc1.Load(HttpContext.Current.Server.MapPath(TicketDefPath));
                project.WorkItemTypes.Import(doc1.DocumentElement);
                XmlDocument doc2 = new XmlDocument();
                doc2.Load(HttpContext.Current.Server.MapPath(ProjectsFilePath));
                XmlNode root = doc2.DocumentElement;
                XmlNode node = root.SelectSingleNode("//projects");
                XmlNode NewProductNode = doc2.CreateNode(XmlNodeType.Element, "project", null);
                XmlAttribute nameAttrib = doc2.CreateAttribute("name");
                nameAttrib.Value = _project;
                NewProductNode.Attributes.Append(nameAttrib);

                //append it at appropriate place
                node.AppendChild(NewProductNode);
                doc2.Save(HttpContext.Current.Server.MapPath(ProjectsFilePath));
                                
                XmlDocument doc3 = new XmlDocument();
                doc3.Load(HttpContext.Current.Server.MapPath(EscalationsFilePath));
                XmlNode root3 = doc3.DocumentElement;
                XmlNode node3 = root3.SelectSingleNode("//Area_Email_Days");
                XmlNode NewAreaNode = doc3.CreateNode(XmlNodeType.Element, "Area", null);
                XmlAttribute nameAttrib1 = doc3.CreateAttribute("Name");
                nameAttrib1.Value = _project;
                XmlAttribute nameAttrib2 = doc3.CreateAttribute("Days");
                nameAttrib2.Value = "2";
                XmlAttribute nameAttrib3 = doc3.CreateAttribute("Email");
                nameAttrib3.Value = "";
                XmlAttribute nameAttrib4 = doc3.CreateAttribute("Project");
                nameAttrib4.Value = _project;
                NewAreaNode.Attributes.Append(nameAttrib1);
                NewAreaNode.Attributes.Append(nameAttrib2);
                NewAreaNode.Attributes.Append(nameAttrib3);
                NewAreaNode.Attributes.Append(nameAttrib4);
                //append it at appropriate place
                node3.AppendChild(NewAreaNode);
                doc3.Save(HttpContext.Current.Server.MapPath(EscalationsFilePath));

		retval = true;
            }
            catch
            {
                throw;
            }
            return retval;
        }

        public ArrayList ProjectsWithTicketing()
        {
            ArrayList projects = new ArrayList();
            XmlDocument doc = new XmlDocument();
            try
            {
                //doc.Load(HttpContext.Current.Server.MapPath("/App_Data/Projects.xml"));
                
                doc.Load(HttpContext.Current.Server.MapPath(ProjectsPath));
                XmlNodeList projectNodes = doc.DocumentElement.SelectNodes("/projects/project");
                foreach (XmlNode projectNode in projectNodes)
                {
                    projects.Add(projectNode.Attributes["name"].Value);
                }
            }
            catch
            {

                throw;
            }
            return projects;

        }
        
        public bool DeleteTicket(int id, string sProject)
        {
            #region Get Variable Values from existing config file
            string uName;
            string passwd;
            string domain;
            string tfs;
            string collection;
            string _project;
            SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
            #endregion

            TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
            WorkItemStore wiStore = tpc.GetService<WorkItemStore>();
            int[] ids = new int[] {id};
            IEnumerable<WorkItemOperationError> Errors;
            Errors = wiStore.DestroyWorkItems(ids);
            List<WorkItemOperationError> errorList = new List<WorkItemOperationError>(Errors);
            if (errorList.Count > 0) return false;
            else return true;
        }

        public void CopyTicket(int id, string sProject, string dProject)
        {
            #region Get Variable Values from existing config file
            string uName;
            string passwd;
            string domain;
            string tfs;
            string collection;
            string _project;
            SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
            #endregion

            TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
            WorkItemStore wiStore = tpc.GetService<WorkItemStore>();
            WorkItem wi = wiStore.GetWorkItem(id);

            Project TargetProject = wiStore.Projects["dProject"];
            WorkItem wiCopy = new WorkItem(TargetProject.WorkItemTypes["Ticket"]);
            wiCopy.Title = wi.Title;
            wiCopy.Description = wi.Description;
            wiCopy.Save();
        }
        public void UploadReports(string teamproject)
        {
            //loop through a folder to get all rdl files
            XmlDocument doc = new XmlDocument();
            doc.Load(HttpContext.Current.Server.MapPath(ProcessConfigPath));
            XmlNode root = doc.DocumentElement;
            string reportservername = root.SelectSingleNode("/configuration/appSettings/add[@key='ReportServerName']").Attributes["value"].Value;
            string collection = root.SelectSingleNode("/configuration/appSettings/add[@key='Collection']").Attributes["value"].Value;
            string path = HttpContext.Current.Server.MapPath("/TicketM/Reports");
            //get credentials 
            string username = root.SelectSingleNode("/configuration/appSettings/add[@key='UserName']").Attributes["value"].Value;
            string password = root.SelectSingleNode("/configuration/appSettings/add[@key='Password']").Attributes["value"].Value;
            string domain = root.SelectSingleNode("/configuration/appSettings/add[@key='Domain']").Attributes["value"].Value;
            //@"C:\Users\administrator.SSGS\Documents\Reports";
            string[] files = Directory.GetFiles(path);
            foreach (string file in files)
            {
                //change the team projet name in the oroginal file
                string str = File.ReadAllText(file);
                string teamProject = "[" + teamproject + "]";
                str = str.Replace("[SSGS EMS]", teamProject);
                File.WriteAllText(file, str);
                // find only name of file 
                string[] stringSeparators = new string[] { "\\" };
                string[] result;
                result = file.Split(stringSeparators, StringSplitOptions.None);
                string reportName = result[result.Length - 1].Substring(0, result[result.Length - 1].Length - 4);
                ReportService.ReportingService2010 rs = new ReportService.ReportingService2010();

                //NetworkCredential credentials = new NetworkCredential("administrator", "P2ssw0rd", "SSGS");
                NetworkCredential credentials = new NetworkCredential(username, password, domain);
                rs.Credentials = credentials;
                rs.Url = "http://" + reportservername + "/reportserver/ReportService2010.asmx";
                //find if the folder already exists
                //this team project tp is without square brackets

                ReportService.CatalogItem[] items = rs.ListChildren("/TfsReports/" + collection + "/" + teamproject, true);
                //localhost.CatalogItem[] items = rs.ListChildren("/TfsReports/DefaultCollection/" + teamproject, true);
                ReportService.CatalogItem item = null;
                bool exists = false;
                foreach (CatalogItem folder in items)
                {
                    if (folder.Name == "TicketM")
                    {
                        // Console.WriteLine("folder exists");
                        exists = true;
                    }

                }
                //create TicketM folder if it does not exist
                if (!exists)
                {
                    item = rs.CreateFolder("TicketM", "/TfsReports/" + collection + "/" + teamproject, null);
                }
                byte[] definition = null;
                Warning[] warnings = null;
                FileStream stream = File.OpenRead(file);
                definition = new Byte[stream.Length];
                stream.Read(definition, 0, (int)stream.Length);
                stream.Close();
                rs.CreateCatalogItem("Report", reportName, "/TfsReports/" + collection + "/" + teamproject + "/TicketM", true, definition, null, out warnings);
                //rs.CreateCatalogItem("Report", reportName, "/TfsReports/DefaultCollection/" + teamproject + "/TicketM", true, definition, null, out warnings);
                //replace  file contets back to previous one
                str = File.ReadAllText(file);
                str = str.Replace(teamProject, "[SSGS EMS]");
                File.WriteAllText(file, str);


            }
        }
        public bool UpdateRouting(string sProject)
        {
            #region Get Variable Values from existing config file
            string uName;
            string passwd;
            string domain;
            string tfs;
            string collection;
            string _project;
            Models.Tickets.SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
            #endregion

            #region Connect to TFS, get project name and Ticket Type

            TfsTeamProjectCollection tpc = Models.Tickets.Connect2Tfs(uName, passwd, domain, tfs, collection);
            var wiStore = tpc.GetService<WorkItemStore>();
            var project = wiStore.Projects[_project];
            WorkItemType wiType = project.WorkItemTypes["Ticket"];
            #endregion

            #region Read Area Structure from a local file and get AreaIds for each AreaPath
            XmlDocument tempDoc = new XmlDocument();
            tempDoc.Load(HttpContext.Current.Server.MapPath(RoutingConfigPath));
            XmlNode ProjectNode = tempDoc.DocumentElement.SelectSingleNode("/Project[@Name='" + _project + "']");


            XmlNodeList AllAreaPathNodes = ProjectNode.ChildNodes;
            
            TicketM.Models.Tickets ticket = new Models.Tickets();
            List<int> areaIds = new List<int>();
            foreach (XmlNode areaPath in AllAreaPathNodes)
            {
                areaIds.Add(ticket.GetAreaId(areaPath.Attributes["Name"].Value.ToString(), sProject));
            }
            #endregion

            #region Read Ticket type definition and get AssignedTo field with constraints
            XmlDocument doc1 = wiType.Export(true);
            XmlNode root1 = doc1.DocumentElement;
            XmlNode AssignedToNode = root1.SelectSingleNode("//FIELDS/FIELD[@name='Assigned To']");
            #endregion


            int ctr = 0;
            while (ctr < areaIds.Count)
            {
                XmlNode AssigneeNode = AssignedToNode.SelectSingleNode("WHEN[@value='" + areaIds[ctr] + "']/*/*");
                if (AssigneeNode != null)
                {
                    AssigneeNode.Attributes["value"].Value = AllAreaPathNodes[ctr].Attributes[0].Value;
                }
                else if (AllAreaPathNodes[ctr].InnerXml != "")
                {
                    XmlNode WhenNode = doc1.CreateNode(XmlNodeType.Element, "WHEN", null);
                    XmlAttribute fieldAttrib = doc1.CreateAttribute("field");
                    fieldAttrib.Value = "System.AreaId";
                    XmlAttribute valueAttrib = doc1.CreateAttribute("value");
                    valueAttrib.Value = areaIds[ctr].ToString();
                    WhenNode.Attributes.Append(fieldAttrib);
                    WhenNode.Attributes.Append(valueAttrib);

                    XmlNode AllowedValuesNode = doc1.CreateNode(XmlNodeType.Element, "ALLOWEDVALUES", null);
                    XmlAttribute expandAttrib = doc1.CreateAttribute("expanditems");
                    expandAttrib.Value = "true";
                    AllowedValuesNode.Attributes.Append(expandAttrib);

                    XmlNode ListItemNode = doc1.CreateNode(XmlNodeType.Element, "LISTITEM", null);
                    XmlAttribute valueAttrib2 = doc1.CreateAttribute("value");
                    valueAttrib2.Value = AllAreaPathNodes[ctr].FirstChild.InnerText;
                    ListItemNode.Attributes.Append(valueAttrib2);

                    AllowedValuesNode.AppendChild(ListItemNode);
                    WhenNode.AppendChild(AllowedValuesNode);
                    AssignedToNode.AppendChild(WhenNode);
                }
                ctr++;
            }
            project.WorkItemTypes.Import(doc1.InnerXml);
            return true;
        }

        internal void MoveTicket(string project, string ticketId)
        {
            try
            {
                #region Get Variable Values from existing config file
                string uName;
                string passwd;
                string domain;
                string tfs;
                string collection;
                string _project;
                SetGenVarValues(project, out uName, out passwd, out domain, out tfs, out collection, out _project);
                #endregion

                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);

                WorkItemStore wiStore = tpc.GetService<WorkItemStore>();
                WorkItem wiSource = wiStore.GetWorkItem(Convert.ToInt32(ticketId));
                WorkItem wiDestination = new WorkItem(wiStore.Projects[project].WorkItemTypes["Ticket"]);
                wiDestination.Title = wiSource.Title;
                wiDestination.Description = wiSource.Description;
                wiDestination.Save();
                List<int> WI2Destroy = new List<int>();
                WI2Destroy.Add(wiSource.Id);
                wiStore.DestroyWorkItems(WI2Destroy);
            }
            catch
            {
                Logger.CreateLogEntry("Failed to move work item " + ticketId);
            }
        }
    }

}